// 日程相关时间计算工具类
var moment = require('moment');
var config = require('../conf/config');
var period = config.constant.period;

module.exports =    function(){

    var addDay = function(date, day){
        var m = moment(date);
        m.add(day, 'day');
        return m.toDate();
    };

    var addWeek = function(date, week){
        var m = moment(date);
        m.add(week, 'week');
        return m.toDate();
    };

    var addMonth = function(date, month){
        var today = date.getDate();
        var m = null;

        do {
            m = moment(date);
            m.add(month, 'month');
            month = month > 0 ? ++month : --month;
        } while(m.date() != today);

        return m.toDate();
    };

    var addYear = function(date, year){
        var today = date.getDate();
        var m = null;

        do {
            m = moment(date);
            m.add(year, 'year');
            year = year > 0 ? ++year : --year;
        } while(m.date() != today);

        return m.toDate();
    };

    // 计算下一次执行时间
    var computeNextExecTime = function(customRemind){
        switch (customRemind.repeat) {
            case period.DAY :
                customRemind.alarm = addDay(customRemind.alarm, 1);
                break;
            case period.WEEK :
                customRemind.alarm = addWeek(customRemind.alarm, 1);
                break;
            case period.MONTH :
                customRemind.alarm = addMonth(customRemind.alarm, 1);
                break;
            case period.YEAR :
                customRemind.alarm = addYear(customRemind.alarm, 1);
                break;
            case period.NONE :
                break;
            default :
                console.error('无按%s类型重复项', customRemind.repeat);
        }

        return customRemind;
    };

    // 计算当前类型的下一次时间
    var computeNextTimeByType = function(dateTime, repeatType, queryType){
        var returnTime = dateTime;
        var step = queryType == config.constant.queryType.BACK ? -1 : 1;

        switch (repeatType) {
            case period.DAY :
                returnTime= addDay(dateTime, step);
                break;
            case period.WEEK :
                returnTime = addWeek(dateTime, step);
                break;
            case period.MONTH :
                returnTime = addMonth(dateTime, step);
                break;
            case period.YEAR :
                returnTime = addYear(dateTime, step);
                break;
            case period.NONE :
                break;
            default :
                console.error('无按%s类型重复项', type);
        }

        return returnTime;
    };

    // 从新开始计算时间
    var recalculateNextRemindTime = function (startTime, leadMinute, remindPeriod) {
        var finalDate;
        startTime = startTime instanceof Date ? startTime : moment(startTime).toDate();

        switch (remindPeriod) {
            case period.DAY :
                finalDate = culateNextRemindTime(startTime, leadMinute, addDay, 'day');
                break;
            case period.WEEK :
                finalDate = culateNextRemindTime(startTime, leadMinute, addWeek, 'week');
                break;
            case period.MONTH :
                finalDate = culateNextRemindTime(startTime, leadMinute, addMonth, 'month');
                break;
            case period.YEAR :
                finalDate = culateNextRemindTime(startTime, leadMinute, addYear, 'year');
                break;
            case period.NONE :
                finalDate = startTime;
                break;
            default :
                console.error('无按%s类型重复项', remindPeriod);
        }

        return finalDate;
    };

    var culateNextRemindTime = function (startTime, leadMinute, addPeriodFunction, type) {
        var nextStartTime = startTime;
        var minute = -leadMinute;

        // 如果当前时间比开始时间大，则计算下次执行时间，否则只计算提前分钟数
        if (moment().diff(nextStartTime) > 0) {
            var diff = moment().diff(nextStartTime, type);
            nextStartTime = addPeriodFunction(nextStartTime, diff);

            // 纠正后如果还是小于当前时间，说明当前己过了会义或任务提醒时间，需要到下一个时间
            if (moment().diff(nextStartTime) > 0) {

                nextStartTime = addPeriodFunction(nextStartTime, 1);
            }
        }

        return moment(nextStartTime).add(minute, 'minute').toDate();
    };


    // 为列表按数量分页计算服务，用于计算重复时间指定点的下一时间
    var recalculateEntryPointTime = function (startTime, pointTime, remindPeriod, queryType, isFirstPage) {
        startTime = startTime instanceof Date ? startTime : moment(startTime).toDate();
        pointTime = pointTime instanceof Date ? pointTime : moment(pointTime).toDate();
        var finalDate = startTime;

        switch (remindPeriod) {
            case period.DAY :
                finalDate = calculateEntryPointTime(startTime, pointTime, addDay, 'day', queryType, isFirstPage);
                break;
            case period.WEEK :
                finalDate = calculateEntryPointTime(startTime, pointTime, addWeek, 'week', queryType, isFirstPage);
                break;
            case period.MONTH :
                finalDate = calculateEntryPointTime(startTime, pointTime, addMonth, 'month', queryType, isFirstPage);
                break;
            case period.YEAR :
                finalDate = calculateEntryPointTime(startTime, pointTime, addYear, 'year', queryType, isFirstPage);
                break;
            case period.NONE :
                finalDate = startTime;
                break;
            default :
                console.error('无按%s类型重复项', remindPeriod);
        }

        return finalDate;
    };

    var calculateEntryPointTime = function (startTime, pointTime, addPeriodFunction, repeatType, queryType, isFirstPage) {
        var nextStartTime = startTime;
        var pointTimeMon = moment(pointTime);

        // 如果指定时间比开始时间大，则计算下次执行时间
        if (pointTimeMon.diff(nextStartTime) > 0) {
            var diff = pointTimeMon.diff(nextStartTime, repeatType);
            nextStartTime = addPeriodFunction(nextStartTime, diff);

            // 如果不是第一次请求，且纠正后如果还是小于当前时间，说明当前己过了会义或任务提醒时间，需要到下一个时间
            if (isFirstPage) {
                if (queryType == config.constant.queryType.NEXT && pointTimeMon.diff(nextStartTime) > 0) {
                    nextStartTime = addPeriodFunction(nextStartTime, 1);
                } else if(queryType == config.constant.queryType.BACK && pointTimeMon.diff(nextStartTime) < 0) {
                    nextStartTime = addPeriodFunction(nextStartTime, -1);
                }
            } else {
                if (queryType == config.constant.queryType.NEXT && pointTimeMon.diff(nextStartTime) >= 0) {
                    nextStartTime = addPeriodFunction(nextStartTime, 1);
                } else if(queryType == config.constant.queryType.BACK && pointTimeMon.diff(nextStartTime) <= 0) {
                    nextStartTime = addPeriodFunction(nextStartTime, -1);
                }
            }
        }

        return nextStartTime;
    };

    return {
        nextExecTime : computeNextExecTime,
        addDay :   addDay,
        addWeek :  addWeek,
        addMonth : addMonth,
        addYear    :   addYear,
        recalculateNextRemindTime : recalculateNextRemindTime,
        computeNextTimeByType : computeNextTimeByType,
        recalculateEntryPointTime : recalculateEntryPointTime
    };
}();